package model

import (
	"database/sql/driver"
	"strconv"
	"strings"

	"github.com/pkg/errors"
)

// Long 64位长整型ID,前端返回位字符串
type Long struct {
	val int64 // 实际值
}

func NewLong(id string) (Long, error) {
	i, err := strconv.ParseInt(id, 10, 64)
	if err != nil {
		return Long{}, err
	}
	return Long{val: i}, nil
}

func LongOfInt64(i int64) Long {
	return Long{val: i}
}

func (s Long) String() string {
	return strconv.FormatInt(s.val, 10)
}

func (s Long) Val() int64 {
	return s.val
}

func (s *Long) MarshalJSON() ([]byte, error) {
	r := s.String()
	builder := &strings.Builder{}
	builder.WriteString("\"")
	builder.WriteString(r)
	builder.WriteString("\"")
	return []byte(builder.String()), nil
}

func (s *Long) UnmarshalJSON(b []byte) error {
	v := string(b)
	v = strings.ReplaceAll(v, "\"", "")
	i, err := strconv.ParseInt(v, 10, 64)
	if err != nil {
		return err
	}
	s.val = i
	return nil
}

func (s Long) Value() (driver.Value, error) {
	return s.val, nil
}

func (s *Long) Scan(v interface{}) error {
	switch v.(type) {
	case int64:
		s.val = v.(int64)
		return nil
	case uint64:
		s.val = int64(v.(uint64))
		return nil
	case []byte:
		i, err := strconv.ParseInt(string(v.([]byte)), 10, 64)
		if err != nil {
			return errors.New("Long scan error, convert string byte array to int64 fail")
		}
		s.val = i
		return nil
	}
	return errors.New("Long scan error")
}
